Branching Fractal




""" Branching Fractal - Tom Fangrow, 5/13/2026 """

from tkinter import *
import math, random
 
root = Tk()
root.geometry('1600x1290')
root.title('Branching Fractal')

canvas = Canvas(root, width=1600, height=1200, bg='#AAAAAA', highlightthickness=0)
canvas.grid(row=0, column=0, columnspan=5)

def branching():
    canvas.delete('all')                                        # start with clean canvas
    branches = []
    color=''
    branch = canvas.create_line(800, 1200, 800, 1200-trunk_slider.get(), width=.1*trunk_slider.get(), fill="#220800")   # trunk  
    branches.append(branch)

    for branch in branches:                                     # ever-expanding "loop" (select one, create two more)
        x1 = canvas.coords(branch)[0]                            
        y1 = canvas.coords(branch)[1]
        x2 = canvas.coords(branch)[2]
        y2 = canvas.coords(branch)[3]
        length = math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))   # parent length
        if length < 80:
            color='#008000'                                     # green
        else:
            color='#220800'                                     # brown
        if length < 10:                             # stop branching when branches are too short (otherwise it branches forever)
            break
        w = .08*length                              # w = width of line (branch)
        e = 2*random_slider.get()                   # e = arbitrary degree of randomness
        ratio = branch_slider.get()/100             # branch length as a fraction of trunk length 
        
        a = math.atan2(y1-y2, x2-x1)                                    # parent angle in radians (+y is down)
        b = .01*random.randint(-e, e)+angle_slider.get()*math.pi/360    # child half-angle in radians
        c = random.randint(-e, e)+length*ratio                          # child length
        
        branch = canvas.create_line(x2, y2, x2+c*math.cos(a+b), y2-c*math.sin(a+b), fill=color, width=w) # left child
        branches.append(branch)
        branch = canvas.create_line(x2, y2, x2+c*math.cos(a-b), y2-c*math.sin(a-b), fill=color, width=w) # right child
        branches.append(branch)
        canvas.update()
            
start_button = Button(root, text=' DRAW FRACTAL ', command=branching)
start_button.grid(row=2, column=4, pady=10)

trunk_slider = Scale(root, from_=60, to=600, length=250, orient=HORIZONTAL)
trunk_slider.grid(row=2, column=0)
trunk_slider.set(350)
trunk_label = Label(root, text='trunk length (pixels)')
trunk_label.grid(row=3, column=0)

branch_slider = Scale(root, from_=20, to=100, length=250, orient=HORIZONTAL)
branch_slider.grid(row=2, column=1)
branch_slider.set(70)
branch_label = Label(root, text='branch length (% of trunk length)')
branch_label.grid(row=3, column=1)

angle_slider = Scale(root, from_=5, to=180, length=250, orient=HORIZONTAL)
angle_slider.grid(row=2, column=2)
angle_slider.set(50)
angle_label = Label(root, text='branch angle (degrees)')
angle_label.grid(row=3, column=2)

random_slider = Scale(root, from_=0, to=11, length=100, orient=HORIZONTAL)
random_slider.grid(row=2, column=3)
random_slider.set(3)
random_label = Label(root, text='randomness')
random_label.grid(row=3, column=3)

root.mainloop()

Back to Tom Fangrow's Home Page